<?php

namespace App\Services;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class PerformanceService
{
    protected $logService;

    public function __construct(LogService $logService)
    {
        $this->logService = $logService;
    }

    /**
     * 监控数据库查询性能
     */
    public function monitorDatabaseQueries(): void
    {
        DB::listen(function ($query) {
            $this->logService->logDatabaseQuery(
                $query->sql,
                $query->time,
                $query->bindings
            );
        });
    }

    /**
     * 监控内存使用
     */
    public function monitorMemoryUsage(): array
    {
        $memoryUsage = memory_get_usage(true);
        $peakMemory = memory_get_peak_usage(true);
        
        $metrics = [
            'current_memory' => $memoryUsage,
            'peak_memory' => $peakMemory,
            'current_memory_mb' => round($memoryUsage / 1024 / 1024, 2),
            'peak_memory_mb' => round($peakMemory / 1024 / 1024, 2),
            'memory_limit' => ini_get('memory_limit'),
        ];

        $this->logService->logPerformance('memory_usage', 0, $metrics);
        
        return $metrics;
    }

    /**
     * 监控执行时间
     */
    public function measureExecutionTime(callable $callback, string $operation = 'operation'): mixed
    {
        $startTime = microtime(true);
        $startMemory = memory_get_usage(true);
        
        try {
            $result = $callback();
            
            $endTime = microtime(true);
            $endMemory = memory_get_usage(true);
            
            $duration = ($endTime - $startTime) * 1000; // 转换为毫秒
            $memoryUsed = $endMemory - $startMemory;
            
            $this->logService->logPerformance($operation, $duration, [
                'memory_used' => $memoryUsed,
                'memory_used_mb' => round($memoryUsed / 1024 / 1024, 2),
            ]);
            
            return $result;
            
        } catch (\Exception $e) {
            $endTime = microtime(true);
            $duration = ($endTime - $startTime) * 1000;
            
            $this->logService->logPerformance($operation . '_error', $duration, [
                'error' => $e->getMessage(),
            ]);
            
            throw $e;
        }
    }

    /**
     * 监控API响应时间
     */
    public function monitorApiResponse(string $method, string $url, callable $callback): mixed
    {
        return $this->measureExecutionTime($callback, "api_{$method}_{$url}");
    }

    /**
     * 监控缓存性能
     */
    public function monitorCacheOperation(string $operation, callable $callback): mixed
    {
        return $this->measureExecutionTime($callback, "cache_{$operation}");
    }

    /**
     * 获取系统性能指标
     */
    public function getSystemMetrics(): array
    {
        $memory = $this->monitorMemoryUsage();
        
        return [
            'memory' => $memory,
            'php_version' => PHP_VERSION,
            'laravel_version' => app()->version(),
            'server_time' => now()->toISOString(),
            'timezone' => config('app.timezone'),
            'environment' => config('app.env'),
            'debug_mode' => config('app.debug'),
        ];
    }

    /**
     * 获取数据库性能指标
     */
    public function getDatabaseMetrics(): array
    {
        try {
            $connection = DB::connection();
            $pdo = $connection->getPdo();
            
            return [
                'driver' => $connection->getDriverName(),
                'version' => $pdo->getAttribute(\PDO::ATTR_SERVER_VERSION),
                'connection_status' => $pdo->getAttribute(\PDO::ATTR_CONNECTION_STATUS),
                'server_info' => $pdo->getAttribute(\PDO::ATTR_SERVER_INFO),
            ];
        } catch (\Exception $e) {
            return [
                'error' => $e->getMessage(),
            ];
        }
    }

    /**
     * 获取缓存性能指标
     */
    public function getCacheMetrics(): array
    {
        $driver = config('cache.default');
        
        try {
            $cache = Cache::store();
            
            return [
                'driver' => $driver,
                'status' => 'connected',
                'info' => $this->getCacheInfo($driver),
            ];
        } catch (\Exception $e) {
            return [
                'driver' => $driver,
                'status' => 'error',
                'error' => $e->getMessage(),
            ];
        }
    }

    /**
     * 获取缓存信息
     */
    private function getCacheInfo(string $driver): array
    {
        switch ($driver) {
            case 'redis':
                try {
                    $redis = Cache::store('redis')->getRedis();
                    return [
                        'version' => $redis->info()['redis_version'] ?? 'unknown',
                        'memory_used' => $redis->info()['used_memory_human'] ?? 'unknown',
                        'connected_clients' => $redis->info()['connected_clients'] ?? 'unknown',
                    ];
                } catch (\Exception $e) {
                    return ['error' => $e->getMessage()];
                }
                
            case 'file':
                return [
                    'storage_path' => config('cache.stores.file.path'),
                ];
                
            default:
                return ['driver' => $driver];
        }
    }

    /**
     * 性能基准测试
     */
    public function benchmark(callable $callback, int $iterations = 100): array
    {
        $times = [];
        
        for ($i = 0; $i < $iterations; $i++) {
            $startTime = microtime(true);
            $callback();
            $endTime = microtime(true);
            
            $times[] = ($endTime - $startTime) * 1000;
        }
        
        sort($times);
        
        return [
            'iterations' => $iterations,
            'min_time' => min($times),
            'max_time' => max($times),
            'avg_time' => array_sum($times) / count($times),
            'median_time' => $times[intval(count($times) / 2)],
            'p95_time' => $times[intval(count($times) * 0.95)],
            'p99_time' => $times[intval(count($times) * 0.99)],
        ];
    }

    /**
     * 检查性能阈值
     */
    public function checkPerformanceThresholds(): array
    {
        $memory = $this->monitorMemoryUsage();
        $memoryUsagePercent = ($memory['current_memory'] / $this->parseMemoryLimit($memory['memory_limit'])) * 100;
        
        $warnings = [];
        
        if ($memoryUsagePercent > 80) {
            $warnings[] = "内存使用率过高: {$memoryUsagePercent}%";
        }
        
        if ($memory['peak_memory_mb'] > 100) {
            $warnings[] = "峰值内存使用过高: {$memory['peak_memory_mb']}MB";
        }
        
        return [
            'warnings' => $warnings,
            'memory_usage_percent' => $memoryUsagePercent,
            'status' => empty($warnings) ? 'healthy' : 'warning',
        ];
    }

    /**
     * 解析内存限制
     */
    private function parseMemoryLimit(string $limit): int
    {
        $limit = trim($limit);
        $last = strtolower($limit[strlen($limit) - 1]);
        $limit = (int) $limit;
        
        switch ($last) {
            case 'g':
                $limit *= 1024;
            case 'm':
                $limit *= 1024;
            case 'k':
                $limit *= 1024;
        }
        
        return $limit;
    }
}
